/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
 */
 
#include "fosfor_tracker.h"
#include "support.h"

G_DEFINE_TYPE(FosforTracker, fosfor_tracker, CLUTTER_TYPE_GROUP);
static GObjectClass *parent_class = NULL;

static void fosfor_tracker_dispose(GObject * object);
static void fosfor_tracker_paint(ClutterActor *actor);
static void fosfor_tracker_allocate(ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags);

static gboolean on_rect_enter(ClutterActor * actor, ClutterEvent * event, gpointer data)
{
	FosforTracker *tracker = FOSFOR_TRACKER(actor);
	ClutterColor *black;

	black = clutter_color_new(0, 0, 0, 255);	
	
	clutter_actor_animate(tracker->background, CLUTTER_LINEAR, 100, "opacity", 0xaa, NULL);
	//clutter_text_set_color(CLUTTER_TEXT(tracker->status),black);
	//clutter_text_set_color(CLUTTER_TEXT(tracker->time_stamp),black);

	return TRUE;
}

static gboolean on_rect_leave(ClutterActor * actor, ClutterEvent * event, gpointer data)
{
	FosforTracker *tracker = FOSFOR_TRACKER(actor);
	ClutterColor *white;

	white = clutter_color_new(255,255,255,255);
	
	clutter_actor_animate(tracker->background, CLUTTER_LINEAR, 100, "opacity", 0x00, NULL);
	//clutter_text_set_color(CLUTTER_TEXT(tracker->status),white);
	//clutter_text_set_color(CLUTTER_TEXT(tracker->time_stamp),white);
	    
	return TRUE;
}

static gboolean on_button_press(ClutterActor * actor, ClutterButtonEvent * event, gpointer data)
{
	FosforTracker *tracker = FOSFOR_TRACKER(data);
	if (event->button == 1) {
		tracker->mouse_down = TRUE;
	}
	return TRUE;
}

static gboolean on_button_release(ClutterActor * actor, ClutterButtonEvent * event, gpointer data)
{
	guint value;
	gfloat actor_x, actor_y;
	
	FosforTracker *tracker = FOSFOR_TRACKER(data);
	if (event->button == 1 && tracker->mouse_down) {
		clutter_actor_transform_stage_point(actor, event->x, event->y, &actor_x, &actor_y);
		value = (actor_x / tracker->width) * tracker->duration;	
		tracker->mouse_down = FALSE;
		fosfor_tracker_set_value(tracker, value);
		g_signal_emit_by_name(tracker, "percentage-changed", tracker->percentage);
		
	}

	return TRUE;
}

static gboolean on_scroll_event(ClutterActor * actor, ClutterScrollEvent * event, gpointer data)
{
	FosforTracker *tracker = FOSFOR_TRACKER(data);
	
	if (event->direction == CLUTTER_SCROLL_UP)
		fosfor_tracker_set_value(tracker, tracker->position + 10);
	if (event->direction == CLUTTER_SCROLL_DOWN)
		fosfor_tracker_set_value(tracker, tracker->position - 10);
	g_signal_emit_by_name(tracker, "percentage-changed", tracker->percentage);

	return FALSE;
}


static void fosfor_tracker_class_init(FosforTrackerClass * class)
{
	parent_class = g_type_class_peek_parent(class);
	G_OBJECT_CLASS(class)->dispose = fosfor_tracker_dispose;
	CLUTTER_ACTOR_CLASS(class)->paint = fosfor_tracker_paint;
	CLUTTER_ACTOR_CLASS(class)->allocate = fosfor_tracker_allocate;

	g_signal_new("percentage-changed", FOSFOR_TYPE_TRACKER, 
	    								G_SIGNAL_RUN_LAST, 
	    								G_STRUCT_OFFSET (FosforTrackerClass, percentage_changed), 
	    								NULL, NULL,
	    								g_cclosure_marshal_VOID__DOUBLE,G_TYPE_NONE,1,G_TYPE_DOUBLE);
	
}

static void fosfor_tracker_init(FosforTracker * tracker)
{
	// class init stuff

	clutter_actor_set_reactive(CLUTTER_ACTOR(tracker), TRUE);
	g_signal_connect(CLUTTER_ACTOR(tracker), "enter-event", G_CALLBACK(on_rect_enter), NULL);
    g_signal_connect(CLUTTER_ACTOR(tracker), "leave-event", G_CALLBACK(on_rect_leave), NULL);

}

static void fosfor_tracker_dispose(GObject * object)
{
	G_OBJECT_CLASS(parent_class)->dispose(object);
}

static void fosfor_tracker_paint(ClutterActor *actor)
{
	FosforTracker *tracker = FOSFOR_TRACKER(actor);
	cairo_t *cr;

	if (tracker->width == 0 || tracker->height == 0)
		return;

	clutter_cairo_texture_set_surface_size(CLUTTER_CAIRO_TEXTURE(tracker->background), tracker->width, tracker->height);
	clutter_cairo_texture_clear(CLUTTER_CAIRO_TEXTURE(tracker->background));

	cr = clutter_cairo_texture_create(CLUTTER_CAIRO_TEXTURE(tracker->background));

  	/* draw on the context */
	cairo_set_source_rgb(cr, 1.0,1.0,1.0);
	cairo_set_line_width(cr, 2.0);
	cairo_rounded_rectangle(cr, 0.0,0.0, tracker->width ,tracker->height, 10.0);

	cairo_fill_preserve(cr);

	cairo_stroke(cr);	
	cairo_destroy (cr);

//printf("tracker width x height = %i x %i\n", tracker->width, tracker->height);
	
	clutter_cairo_texture_set_surface_size(CLUTTER_CAIRO_TEXTURE(tracker->progress), tracker->width, 14.0);

	clutter_cairo_texture_clear(CLUTTER_CAIRO_TEXTURE(tracker->progress));

	cr = clutter_cairo_texture_create(CLUTTER_CAIRO_TEXTURE(tracker->progress));


	cairo_set_source_rgb(cr, window->style->bg[1].red / 65535.0, window->style->bg[1].green / 65535.0, window->style->bg[1].blue / 65535.0);	
	cairo_set_line_width(cr, 1.0);
	cairo_rectangle(cr, 2.0,2.0, clutter_actor_get_width(CLUTTER_ACTOR(tracker)) - 4.0,10.0);
	cairo_fill_preserve(cr);
	cairo_stroke(cr);

	cairo_set_source_rgb(cr, window->style->light[3].red / 65535.0, window->style->light[3].green / 65535.0, window->style->light[3].blue / 65535.0);	
	cairo_set_line_width(cr, 1.0);
	cairo_rectangle(cr, 2.0,2.0, (clutter_actor_get_width(CLUTTER_ACTOR(tracker))-6.0) * tracker->percentage ,10.0);
	cairo_fill_preserve(cr);
	cairo_stroke(cr);

	cairo_set_source_rgb(cr, window->style->dark[1].red / 65535.0, window->style->dark[1].green / 65535.0, window->style->dark[1].blue / 65535.0);	
	cairo_set_line_width(cr, 2.0);
	cairo_rectangle(cr, 2.0,2.0, clutter_actor_get_width(CLUTTER_ACTOR(tracker)) - 4.0,10.0);
	cairo_stroke(cr);	
	
	
	cairo_destroy (cr);

	clutter_actor_set_position(tracker->thumb,((clutter_actor_get_width(CLUTTER_ACTOR(tracker->progress))-6.0) * tracker->percentage) + 3.0,0.0);
	//clutter_actor_set_position(tracker->time_stamp, clutter_actor_get_width(CLUTTER_ACTOR(tracker->progress)) - clutter_actor_get_width(CLUTTER_ACTOR(tracker->time_stamp)), 16.0);

	CLUTTER_ACTOR_CLASS (parent_class)->paint(actor);
}

static void fosfor_tracker_allocate(ClutterActor *actor, const ClutterActorBox *box, ClutterAllocationFlags flags)
{
	FosforTracker *tracker = FOSFOR_TRACKER(actor);
	tracker->width = box->x2-box->x1;
	tracker->height = box->y2-box->y1;

	CLUTTER_ACTOR_CLASS (parent_class)->allocate(actor,box,flags);	
	
}

ClutterActor *fosfor_tracker_new()
{
	FosforTracker *tracker;
	ClutterColor *white;
	ClutterColor *black;
	cairo_t *cr;
	
	tracker = g_object_new (FOSFOR_TYPE_TRACKER, NULL);
	tracker->percentage = 0.0;
	tracker->position = 0;
	tracker->duration = 0;
	white = clutter_color_new(255,255,255,255);
	//black = clutter_color_new(window->style->dark[1].red / 65535.0 * 255, window->style->dark[1].green / 65535.0 * 255, window->style->dark[1].blue / 65535.0 * 255, 128);	
	black = clutter_color_new(0,0,0,255);	

	tracker->background = clutter_cairo_texture_new(10,10);
	clutter_actor_set_opacity(tracker->background, 0x00);			
	clutter_container_add_actor(CLUTTER_CONTAINER(tracker),tracker->background);

	tracker->vlayout = clutter_box_layout_new();
	tracker->vcontainer = clutter_box_new(tracker->vlayout);
	clutter_box_layout_set_pack_start(CLUTTER_BOX_LAYOUT(tracker->vlayout), FALSE);
	clutter_box_layout_set_vertical(CLUTTER_BOX_LAYOUT(tracker->vlayout), TRUE);

	tracker->hlayout = clutter_box_layout_new();
	tracker->hcontainer = clutter_box_new(tracker->hlayout);
	clutter_box_layout_set_pack_start(CLUTTER_BOX_LAYOUT(tracker->hlayout), FALSE);
	
	tracker->progress = clutter_cairo_texture_new(10,10);
	clutter_actor_set_reactive(tracker->progress, TRUE);
	clutter_actor_set_opacity(tracker->progress, 0xff);			
	clutter_box_layout_pack(CLUTTER_BOX_LAYOUT(tracker->vlayout),tracker->progress,TRUE,TRUE,TRUE,CLUTTER_BOX_ALIGNMENT_START,CLUTTER_BOX_ALIGNMENT_START);
	clutter_box_layout_pack(CLUTTER_BOX_LAYOUT(tracker->vlayout),tracker->hcontainer,FALSE,TRUE,FALSE,CLUTTER_BOX_ALIGNMENT_START,CLUTTER_BOX_ALIGNMENT_START);
	
	g_signal_connect(CLUTTER_ACTOR(tracker->progress), "button-press-event", G_CALLBACK(on_button_press), tracker);
    g_signal_connect(CLUTTER_ACTOR(tracker->progress), "button-release-event", G_CALLBACK(on_button_release), tracker);
	g_signal_connect(CLUTTER_ACTOR(tracker->progress), "scroll-event", G_CALLBACK(on_scroll_event), tracker);

	tracker->thumb = clutter_cairo_texture_new(10,20);
	
	
	cr = clutter_cairo_texture_create(CLUTTER_CAIRO_TEXTURE(tracker->thumb));

  	/* draw on the context */
	clutter_cairo_texture_clear(CLUTTER_CAIRO_TEXTURE(tracker->thumb));

	cairo_set_source_rgb(cr, window->style->fg[3].red / 65535.0, window->style->fg[3].green / 65535.0, window->style->fg[3].blue / 65535.0);	
	cairo_set_line_width(cr, 1.0);
	cairo_rounded_rectangle(cr, 1.0,1.0, 6.0, 12.0, 3.0);
	cairo_fill_preserve(cr);
	cairo_stroke(cr);
	cairo_destroy (cr);
	clutter_actor_set_position(tracker->thumb,0.0,0.0);
	
	tracker->status = clutter_text_new();
	clutter_text_set_color(CLUTTER_TEXT(tracker->status), black);
	clutter_text_set_markup(CLUTTER_TEXT(tracker->status),"");
	clutter_box_layout_pack(CLUTTER_BOX_LAYOUT(tracker->hlayout),tracker->status,TRUE,TRUE,FALSE,CLUTTER_BOX_ALIGNMENT_START,CLUTTER_BOX_ALIGNMENT_START);
	
	tracker->time_stamp = clutter_text_new();
	clutter_text_set_color(CLUTTER_TEXT(tracker->time_stamp), black);
	fosfor_tracker_set_duration(tracker, tracker->duration);
	clutter_box_layout_pack(CLUTTER_BOX_LAYOUT(tracker->hlayout),tracker->time_stamp,FALSE,FALSE,FALSE,CLUTTER_BOX_ALIGNMENT_END,CLUTTER_BOX_ALIGNMENT_END);
	clutter_box_layout_set_alignment(CLUTTER_BOX_LAYOUT(tracker->hlayout),tracker->time_stamp,CLUTTER_BOX_ALIGNMENT_END, CLUTTER_BOX_ALIGNMENT_END);
	clutter_text_set_line_alignment(CLUTTER_TEXT(tracker->time_stamp), PANGO_ALIGN_RIGHT);
	
	clutter_color_free(white);
	clutter_color_free(black);

	clutter_actor_hide(tracker->time_stamp);
	
    clutter_container_add_actor(CLUTTER_CONTAINER(tracker),CLUTTER_ACTOR(tracker->vcontainer));
	clutter_container_add_actor(CLUTTER_CONTAINER(tracker),tracker->thumb);
	
	return CLUTTER_ACTOR(tracker);
}

void fosfor_tracker_set_duration(FosforTracker *tracker, guint duration)
{
	gchar *text, *t;

	tracker->duration = abs(duration);
	t = gm_seconds_to_string(duration);
	text = g_strdup_printf("<small>%s</small>",t);
	clutter_text_set_markup(CLUTTER_TEXT(tracker->time_stamp),text);
	g_free(text);
	g_free(t);

}

void fosfor_tracker_set_value(FosforTracker *tracker, guint value)
{
	gchar *text, *d, *p;

	if (value >= tracker->duration)
		return;
	if (value < 0)
		return;
	
	tracker->position = abs(value);
	if (tracker->duration > 0) {
		tracker->percentage = MIN(1.0,(gdouble)tracker->position / (gdouble)tracker->duration);
		p = gm_seconds_to_string(value);
		d = gm_seconds_to_string(tracker->duration);
		text = g_strdup_printf("<small>%s / %s</small>",p,d);
		clutter_text_set_markup(CLUTTER_TEXT(tracker->time_stamp),text);
		g_free(text);
		g_free(d);
		g_free(p);
	} else {
		tracker->percentage = 0.0;
		p = gm_seconds_to_string(value);
		text = g_strdup_printf("<small>%s</small>",p);
		clutter_text_set_markup(CLUTTER_TEXT(tracker->time_stamp),text);
		g_free(text);
		g_free(p);
	}
	//clutter_actor_set_position(tracker->time_stamp, clutter_actor_get_width(CLUTTER_ACTOR(tracker->progress)) - clutter_actor_get_width(CLUTTER_ACTOR(tracker->time_stamp)), 16.0);
	clutter_actor_show(tracker->time_stamp);
}

void fosfor_tracker_set_message(FosforTracker *tracker, const gchar *message)
{
	gchar *text;

	text = g_strdup_printf("<small>%s</small>", message);
	clutter_text_set_markup(CLUTTER_TEXT(tracker->status),text);
	g_free(text);
	
}

gchar *gm_seconds_to_string(gfloat seconds)
{
    guint hour = 0, min = 0, sec = 0;
    gchar *result = NULL;

    if (seconds >= 3600) {
        hour = seconds / 3600;
        seconds = seconds - (hour * 3600);
    }
    if (seconds >= 60) {
        min = seconds / 60;
        seconds = seconds - (min * 60);
    }
    sec = seconds;

    if (hour == 0) {
        result = g_strdup_printf("%2i:%02i", min, sec);
    } else {
        result = g_strdup_printf("%i:%02i:%02i", hour, min, sec);
    }
    return result;
}